package org.example.uhy.domain.model.upgrade.execution.builder;


import org.example.uhy.domain.model.upgrade.execution.node.*;
import org.example.uhy.domain.model.upgrade.schema.UpgradeRule;
import org.example.uhy.domain.model.upgrade.schema.UpgradeRuleType;

import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class UpgradeExecutionNodeFactory {
    private static final UpgradeExecutionNodeFactory instance = new UpgradeExecutionNodeFactory();
    private Map<String, UpgradeExecutionNodeBuilder> ruleExecutionNodeBuilders = new ConcurrentHashMap<>();

    private UpgradeExecutionNodeFactory() {
        ruleExecutionNodeBuilders.put(MemberCountRuleExecutionNode.TYPE, (rule) -> new MemberCountRuleExecutionNode(i(rule.value().get())));
        ruleExecutionNodeBuilders.put(TradeCountRuleExecutionNode.TYPE, (rule) -> new TradeCountRuleExecutionNode(i(rule.value().get())));
        ruleExecutionNodeBuilders.put(TradeMoneyRuleExecutionNode.TYPE, (rule) -> new TradeMoneyRuleExecutionNode(d(rule.value().get())));
    }

    public static UpgradeExecutionNodeFactory instance() {
        return instance;
    }

    public void registerUpgradeExecutionNodeBuilder(String ruleType, UpgradeExecutionNodeBuilder builder) {
        if (ruleType != null && ruleType.length() > 0 && builder != null) {
            ruleExecutionNodeBuilders.put(ruleType, builder);
        }
    }

    public UpgradeExecutionNode createUpgradeExecutionNode(UpgradeRule rule) {
        if (rule.operator().isPresent()) {
            return new LogicalExecutionNode(rule.operator().get());
        } else {
            UpgradeRuleType ruleType = rule.ruleType();
            if (rule.value().isPresent()) {
                if (ruleExecutionNodeBuilders.containsKey(ruleType.getRuleType())) {
                    return ruleExecutionNodeBuilders.get(ruleType.getRuleType()).apply(rule);
                }
            }
        }
        return null;
    }

    private Integer i(String s) {
        return Integer.parseInt(s);
    }

    private Long l(String s) {
        return Long.parseLong(s);
    }

    private BigDecimal d(String s) {
        return new BigDecimal(s);
    }
}
